<?php

# -- DÉBUT NOTE DE LICENCE -------------------------------------
#
# Ce fichier fait partie de Clicpage.
#
# Copyright (c) 2010 Francois (www.clicpage.net)
# Distribué selon les termes de la licence GPL version 2.0.
# Consultez le fichier LICENCE ou
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#
# -- FIN NOTE DE LICENCE ---------------------------------------

/**
@defgroup CP_DONNEES Accès aux données
*/

/**
@ingroup CP_DONNEES
@nosubgrouping
@brief Actions sur une page

Une instance de cpPage représente une page du site.

Ses variables membres permettent d'accéder à toutes les données de la page
issues de la base de données.

Ses méthodes permettent, entre autres, d'effectuer les actions suivantes:
- Modifier la page
- Publier la page
- Supprimer un brouillon et restaurer la version publiée
- Accès à la catégorie parente
- Gestion des tags et commentaires

*Note: C'est le générateur de page qui se charge de la suppression de la page.
*/

class cpPage
{
	
	


	
	protected $core;			///< <b>cpCore</b>		Référence à l'objet cpCore de l'application
	
	protected $version;			// CP_TEMPORAIRE ou CP_PUBLIEE
	
	public $page_id;			///< <b>integer</b>		Identifiant de la page
	public $cat_id;				///< <b>integer</b>		Identifiant de la catégorie
	public $page_generateur;	///< <b>string</b>		Identifiant du générateur de page
	public $page_theme;			///< <b>string</b>		Identifiant du thème
	public $page_statut;		///< <b>integer</b>		Statut de la page (CP_STATUT_ONLINE, CP_STATUT_OFFLINE)
	public $page_modifiee;		///< <b>integer</b>		Présence d'un brouillon (CP_PAGEMODIFIEE_OUI, CP_PAGEMODIFEE_NON)
	public $page_url;			///< <b>string</b>		URL de la page
	public $page_titre;			///< <b>string</b>		Titre de la page
	public $page_entete;		///< <b>string</b>		En-tête de la page
	public $page_entete_xhtml;	///< <b>string</b>		En-tête de la page au format XHTML, prête à être affichée
	public $page_contenu;		///< <b>string</b>		Contenu de la page
	public $page_contenu_xhtml;	///< <b>string</b>		Contenu de la page au format XHTML, prêt à être affiché
	public $page_options;		///< <b>array</b>		Options
	public $page_commentaires;	///< <b>integer</b>		Commentaires (CP_COMMENTAIRES_ACTIFS, CP_COMMENTAIRES_DESACTIVES)
	public $page_acces;			///< <b>integer</b>		Accès à la page (CP_ACCES_TOUS, CP_ACCES_PERMISSION, CP_ACCES_MOT_DE_PASSE)
	public $page_acces_details;	///< <b>string</b>		Détails pour l'accès à la page
	public $page_date;			///< <b>date</b>		Date de création de la page
	public $page_date_modification;		///< <b>date</b>		Date de modification de la page
	public $utilisateur_id;		///< <b>integer</b>		Identifiant de l'auteur de la page
	public $modification_utilisateur_id;///< <b>integer</b>		Identifiant du dernier utilisateur ayant modifié la page
	public $page_mots;			///< <b>string</b>		Mots-clés de la page, pour la recherche
	
	public $generateur;			///< <b>cpGenerateur</b>		Instance de cpGenerateur
	
	private $auteur;			///< <b>cpUtilisateur</b>	Créateur de la page
	
	
	
	

	/// @name Initialisation et mise à jour des valeurs
	//@{
	
	
	/**
	Initialise une instance de cpPage.
	
	Si <var>$version</var> est CP_PUBLIEE, on travaille avec la version publiée
	de la page.
	
	Si <var>$version</var> est CP_TEMPORAIRE, on vérifie s'il existe un
	brouillon de la page. Si oui, on travaille avec le brouillon. Sinon,
	on travaille avec la version publiée.
	
	@param	rs			<b>record</b>		Données de la base de données
	@param	core		<b>cpCore</b>		Référence à cpCore
	@param	version		<b>integer</b>		Version avec laquelle on travaille (CP_PUBLIEE, CP_TEMPORAIRE)
	*/
	public function __construct($rs, $core, $version = CP_PUBLIEE)
	{
		$this->core =& $core;
		$this->setVersion($version);
		$this->initRs($rs);
	}
	
	
	/**
	Définit la version de la page avec laquelle on travaille.

	@param	version		<b>integer</b>		Version avec laquelle on travaille (CP_PUBLIEE, CP_TEMPORAIRE)
	*/
	protected function setVersion($version = CP_PUBLIEE)
	{
		$this->version = $version;
	}
	
	
	/**
	Retourne la version de la page avec laquelle on travaille

	@return	CP_PUBLIEE ou CP_TEMPORAIRE
	*/
	public function getVersion()
	{
		return $this->version;
	}
	
	
	/**
	Met à jour les valeurs de cpPage pour qu'elles correspondent à
	celles de la base de données.
	
	Doit être appelée chaque fois qu'on modifie les données de la page
	dans la base de données.
	*/	
	public function rafraichir()
	{
		$rs = $this->core->site->getPages(array(
			'page_id' => $this->page_id
		), CP_GET_RS);
		
		$this->initRs($rs);
	}
	
	
	protected function initRs($rs)
	{
		
		if($this->version == CP_TEMPORAIRE && $rs->page_modifiee == CP_PAGEMODIFIEE_OUI) {
			$rs = $this->core->site->getPages(array(
				'page_id' => $rs->page_id
			), CP_GET_RS, CP_TEMPORAIRE, 'temp_pages');
		}
		
		$this->page_id = $rs->page_id;
		$this->cat_id = $rs->cat_id;
		$this->page_generateur = $rs->page_generateur;
		$this->page_theme = $rs->page_theme;
		$this->page_statut = $rs->page_statut;
		$this->page_modifiee = $rs->page_modifiee;
		$this->page_langue = $rs->page_langue;
		$this->page_url = $rs->page_url;
		$this->page_titre = $rs->page_titre;
		$this->page_entete = $rs->page_entete;
		$this->page_entete_xhtml = $rs->page_entete_xhtml;
		$this->page_contenu = $rs->page_contenu;
		$this->page_contenu_xhtml = $rs->page_contenu_xhtml;
		$this->page_options = unserialize($rs->page_options);
		$this->page_commentaires = $rs->page_commentaires;
		$this->page_acces = $rs->page_acces;
		$this->page_acces_details = $rs->page_acces_details;
		$this->page_date = $rs->page_date;
		$this->page_date_modification = $rs->page_date_modification;
		$this->utilisateur_id = $rs->utilisateur_id;
		$this->modification_utilisateur_id = $rs->modification_utilisateur_id;
		$this->page_mots = $rs->page_mots;
		unset($this->auteur);
		
		# --COMPORTEMENT-- coreInitRsPage
		$this->core->executerComportement('coreInitRsPage', $rs, $this);
		
	}
	//@}
	
	
	
	

	/// @name Générateur de page
	//@{
	
	
	/**
	Initialise le générateur de page.
	*/
	public function initGenerateur()
	{
		if(!is_object($this->generateur)) {
			if(!array_key_exists($this->page_generateur, $this->core->getGenerateurs())) {
				throw new cpErreur(sprintf(__('Le générateur de page %s n\'a pas pu être chargé.').' '.__('Il a peut-être été désintallé.'), html::escapeHTML($this->page_generateur)), 'page_generateur', 601);
			}
			
			$nomClasse = 'generateur'.$this->page_generateur;
			$this->generateur = new $nomClasse($this, $this->core);
		}
	}
	
	
	/**
	
	Surcharge call
	
	Chaque appel à une méthode qui n'est pas définie dans cpPage est
	transférée au générateur de page.
	*/
	public function __call($nom, $args)
	{
		$this->initGenerateur();
		return call_user_func_array(array($this->generateur, $nom), $args);
	}
	//@}
	
	
	
	

	/// @name Permissions
	//@{
	
	
	/**
	Vérifie si l'utilisateur actuel peut éditer la page.
	
	@return	<b>boolean</b>
	*/
	public function peutModifier()
	{
		if(!$this->core->auth->verifierPermission('pages')) {
			return false;
		}
		if(!$this->core->auth->verifierPermission('toutesPages') && $this->utilisateur_id != $this->core->auth->getUtilisateurID()) {
			return false;
		}
		return true;
	}
	//@}
	
	
	
	

	/// @name Enregistrement et publication
	//@{
	
	
	/**
	Enregistre un brouillon de la page.
		
	@param	donnees	<b>array</b>	Données à enregistrer
	*/
	public function enregistrer($cur)
	{
		
		if(is_array($page_options = $cur->page_options)) {
			$cur->page_options = serialize($cur->page_options);
		}
		
		$cur->page_modifiee 				= CP_PAGEMODIFIEE_OUI;
		$cur->page_date_modification 		= dt::str('%Y-%m-%d %H:%M:%S');
		$cur->modification_utilisateur_id	= (integer) $this->core->auth->getUtilisateurID();
		
		$this->core->site->verifierDonneesPage($cur, false, $this->page_id);
		
		if($this->page_modifiee == CP_PAGEMODIFIEE_NON) {
			
			# Compléter le curseur
			$cur->page_id								= $this->page_id;
			if(!$cur->isField('cat_id'))				{ $cur->cat_id = $this->cat_id; }
			$cur->page_generateur						= $this->page_generateur;
			if(!$cur->isField('page_theme'))			{ $cur->page_theme = $this->page_theme; }
			if(!$cur->isField('page_statut'))			{ $cur->page_statut = $this->page_statut; }
			if(!$cur->isField('page_langue'))			{ $cur->page_langue = $this->page_langue; }
			if(!$cur->isField('page_url'))				{ $cur->page_url = $this->page_url; }
			if(!$cur->isField('page_titre'))			{ $cur->page_titre = $this->page_titre; }
			if(!$cur->isField('page_entete'))			{ $cur->page_entete = $this->page_entete; }
			if(!$cur->isField('page_entete_xhtml'))		{ $cur->page_entete_xhtml = $this->page_entete_xhtml; }
			if(!$cur->isField('page_contenu'))			{ $cur->page_contenu = $this->page_contenu; }
			if(!$cur->isField('page_contenu_xhtml'))	{ $cur->page_contenu_xhtml = $this->page_contenu_xhtml; }
			if(!$cur->isField('page_options'))			{ $cur->page_options = serialize($this->page_options); }
			if(!$cur->isField('page_commentaires'))		{ $cur->page_commentaires = $this->page_commentaires; }
			if(!$cur->isField('page_acces'))			{ $cur->page_acces = $this->page_acces; }
			if(!$cur->isField('page_acces_details'))	{ $cur->page_acces_details = $this->page_acces_details; }
			if(!$cur->isField('page_date'))				{ $cur->page_date = $this->page_date; }
			if(!$cur->isField('utilisateur_id'))		{ $cur->utilisateur_id = $this->utilisateur_id; }
			if(!$cur->isField('page_mots'))				{ $cur->page_mots = $this->page_mots; }
			
			# --COMPORTEMENT-- coreAvantCreerBrouillonPage
			$this->core->executerComportement('coreAvantCreerBrouillonPage', $cur, $this);
			
			$cur->insert();
			$curPub = $this->core->con->openCursor($this->core->prefix.'pub_pages');
			$curPub->page_modifiee = CP_PAGEMODIFIEE_OUI;
			$curPub->update('WHERE page_id = '.(integer) $this->page_id);
			
			# --COMPORTEMENT-- coreApresCreerBrouillonPage
			$this->core->executerComportement('coreApresCreerBrouillonPage', $cur, $this);
			
		}
		else
		{
			
			# --COMPORTEMENT-- coreAvantEnregistrerPage
			$this->core->executerComportement('coreAvantEnregistrerPage', $cur, $this);
			
			$cur->update('WHERE page_id = '.(integer) $this->page_id);
			
			# --COMPORTEMENT-- coreApresEnregistrerPage
			$this->core->executerComportement('coreApresEnregistrerPage', $cur, $this);
			
		}

		$this->rafraichir();
		
	}
	
	
	/**
	Supprime le brouillon.
	
	La version publiée devient alors la seule version disponible.
	*/
	public function restaurer()
	{
		if($this->version != CP_TEMPORAIRE) {
			throw new cpErreur(__('Action non autorisée').' (pas un brouillon)', null, 303);
		}

		$cur = $this->core->con->openCursor($this->core->prefix.'pub_pages');
		$cur->page_modifiee = CP_PAGEMODIFIEE_NON;
		$cur->update('WHERE page_id = '.(integer) $this->page_id);
		
		$this->core->con->execute('DELETE FROM '.$this->core->prefix.'temp_pages '.
			'WHERE page_id = '.(integer) $this->page_id);
		
		$this->rafraichir();
	}
	//@}
	
	
	
	

	/// @name Utilitaires
	//@{
	
	
	/**
	Retourne l'URL absolue de la page.
	
	@return	<b>string</b>	URL absolue
	*/
	public function getURLAbsolue()
	{
		return CP_URL_PUBLIQUE.$this->page_url;
	}
	
	
	/**
	Retourne l'URL relative de la page.
	
	@return	<b>string</b>	URL relative
	*/
	public function getURLRelative()
	{
		return CP_URL_PUBLIQUE_RELATIVE.$this->page_url;
	}
	
	
	/**
	Retourne une instance de cpUtilisateur associée à
	l'auteur de la page (utilisateur_id).
	
	@return	<b>cpUtilisateur</b>
	*/
	public function getAuteur()
	{
		if(!is_object($this->auteur)) {
			$this->auteur = $this->core->site->getUtilisateurs(array(
				'utilisateur_id' => (integer) $this->utilisateur_id
			), CP_GET_STATIC);
		}
		
		return $this->auteur;
	}
	
	/**
	Retourne les identifiants et titres des catégories parents
	
	@return	<b>array</b>
	*/
	public function getArborescence()
	{
		$arb = array();
		$this->calcArborescence($this->cat_id, $arb);
		return array_reverse($arb);
			
	}
	
	
	/** @ignore */
	protected function calcArborescence($cat_id, &$arb)
	{
		$rs = $this->core->con->select('SELECT parent_cat_id, cat_titre, cat_url FROM '.$this->core->prefix.'categories WHERE cat_id = '.(integer) $cat_id);
		$arb[] = array((integer) $rs->cat_id, $rs->cat_titre, $rs->cat_url);
		if($rs->parent_cat_id != 0)
		{
			$this->calcArborescence($rs->parent_cat_id, $arb);
		}
	}
	//@}
	
	
	
	

	/// @name Catégorie
	//@{
	
	
	/**
	Retourne une instance de cpCategorie associée à 
	la catégorie parente de la page.
	
	@return	<b>cpCategorie</b>	Catégorie parente
	*/
	public function getCategorie()
	{
		return $this->core->site->getCategories(array('cat_id' => (integer) $this->cat_id), CP_GET_STATIC);
	}
	
	
	/**
	Indique si la page est la page d'accueil de sa catégorie.
	
	@return	<b>boolean</b>
	*/
	public function isCatHome()
	{
		$parentCat = $this->core->con->select('SELECT home_page_id FROM '.$this->core->prefix.'categories WHERE cat_id = '.(integer) $this->cat_id);
		
		if($parentCat->home_page_id == $this->page_id) {
			return true;
		}
		
		return false;
	}
	
	
	/**
	Indique si la page est la page d'accueil du site.
	
	@return	<b>boolean</b>
	*/
	public function isSiteHome()
	{
		return ((integer) $this->core->site->getPropriete('home_page_id', 'core') == (integer) $this->page_id);
	}
	//@}

	
	
		

	/// @name Tags
	//@{
	
	
	/**
	Retourne un tableau avec les tags associés
	à la page.
	
	@return	<b>array</b>
	*/
	public function getTags()
	{

		$rs = $this->core->con->select(
			'SELECT tag_texte FROM '.$this->core->prefix.'tags '.
			'WHERE page_id = '.(integer) $this->page_id
		);
		
		return $rs;
		
	}
	
	
	/**
	Indique si au moins un tag est associé à la page.
		
	@return	<b>boolean</b>
	*/
	public function hasTag()
	{

		$rs = $this->core->con->select(
			'SELECT count(tag_texte) FROM '.$this->core->prefix.'tags '.
			'WHERE page_id = '.(integer) $this->page_id.' LIMIT 1'
		);
		
		if($rs->f(0) != 0) {
			return true;
		}
		return false;
		
	}
	

	/**
	Vérifie si un tag est déjà associé à la page.
	
	@param	tag	<b>string</b>	Tag à vérifier
	@return	<b>boolean</b>
	*/
	public function checkTag($tag)
	{

		$rs = $this->core->con->select(
			'SELECT count(tag_texte) '.
			'FROM '.$this->core->prefix.'tags '.
			'WHERE page_id = '.(integer) $this->page_id.' '.
			"AND tag_texte = '".$this->core->con->escape($tag)."' LIMIT 1"
		);
		
		return $rs->f(0) == 0 ? false : true;
		
	}
	
		
	/**
	Ajoute un tag à la page.
	
	@param	tag	<b>string</b>	Tag à ajouter
	@param	erreur	<b>boolean</b>	Renvoyer une erreur si le tag existe déjà
	*/
	public function ajouterTag($tag, $erreur=true)
	{
		
		if(empty($tag)) {
			throw new cpErreur(__('Vous devez indiquer un tag.'), 'tag_texte', 101);
		}
		
		if($this->checkTag($tag)) {
			if($erreur) {
				throw new cpErreur(__('Le tag est déjà associé à la page.'), 'tag_texte', 102);
			}
			return false;
		}
		
		$cur = $this->core->con->openCursor($this->core->prefix.'tags');
		$cur->tag_texte = $tag;
		$cur->page_id = (integer) $this->page_id;
		$cur->insert();
		
		return true;
		
	}
	
	
	/**
	Supprime un tag de la page.
	
	@param	tag	<b>string</b>	Tag à supprimer
	*/
	public function supprimerTag($tag)
	{
		
		if(empty($tag)) {
			throw new cpErreur(__('Vous devez indiquer un tag.'), 'tag_texte', 101);
		}
		
		$this->core->con->execute(
			'DELETE FROM '.$this->core->prefix.'tags '.
			"WHERE tag_texte = '".$this->core->con->escape($tag)."' ".
			"AND page_id = ".(integer) $this->page_id." LIMIT 1"
		);
		
	}
	//@}
	
	
	
		

	/// @name Commentaires
	//@{
	
	
	/**
	Retourne un tableau avec un objet cpCommentaire pour chaque commentaire
	de la page.
	
	@param	params	<b>array</b>	Paramètres
	@param	params	<b>integer</b>	Type de résultat à retourner
	@return	<b>recordset</b>	Commentaires de la page
	*/
	public function getCommentaires($params=array(), $type=CP_GET_RS)
	{		
		$params['page_id'] = (integer) $this->page_id;
		return $this->core->site->getCommentaires($params, $type);
	}
	
	
	public function countCommentaires($contexte=0,$statut=CP_COMMENTAIRE_APPROUVE)
	{
		return $this->getCommentaires(array(
			'commentaire_contexte'	=> $contexte,
			'commentaire_statut'	=> $statut
		), CP_GET_COMPTEUR)->f(0);
	}
	//@}
}

?>